import { actionDebounce, toPage } from '@/utils/mpHelper'
import type { MessageMappings, OTAHelper, OTAHelperConfigOptions } from './types'
import type { WS } from '@/utils/socket/types'
import { WebsocketManager } from '@/utils/socket/WebsocketManager'
import { useWebsocketListener } from '@/utils/socket/WebSocketHandlerImp'
import {
  ALLOW_SOFTWARE_UPDATE,
  CONFIRMED,
  CONFIRM_ACKNOWLEDGE,
  OFF,
  PRESENT,
  SOFTWARE_UPDATE_AVAILABLE,
  SOFTWARE_UPDATE_SUCCESSFUL,
} from '@/constants/Command'
import { getAppSupportCommands, getEvents, setCommand } from '@/api/appliance'
import i18n from '@/i18n'
import { getControllerContext } from '@/controller/common/context'

export default class InhouseOtaHelper implements OTAHelper {
  configOptions!: OTAHelperConfigOptions

  upgradeDetected = ref(false) // 是否检测到升级
  remoteUpgradeSupported = ref(true) // 是否支持小程序远程升级
  upgradingModalVisible = ref(false) // 是否显示【固件升级中】弹框
  successModalVisible = ref(false) // 是否显示【固件已升级至最新版本】确认框
  retryModalVisible = ref(false) // 是否显示【网络异常，请重试】弹框

  /**
   * 收到升级成功的event时
   *  - [可选] 不设置时 不处理acknowledge
   *  - auto: 自动下发acknowledge，并弹出toast提醒用户升级成功
   *  - manual: 显示【固件已升级至最新版本】确认框，需要等待用户手动点击【知道了】按钮后再下发acknowledge
   */
  private successAcknowledge?: 'auto' | 'manual'

  constructor(options: OTAHelperConfigOptions) {
    this.configOptions = options
    this.addMessageListener()

    // 设置收到升级成功提示时的处理逻辑
    switch (options.scene) {
      case 'detail':
      case 'setting': {
        this.successAcknowledge = 'manual'
        break
      }
      case 'firmware': {
        this.successAcknowledge = 'auto'
        break
      }
    }
  }

  destroy(): void {
    this.removeMessageListener()
  }

  get haId() {
    return this.configOptions.haId
  }

  async toUpgradePage() {
    const options = this.configOptions
    await toPage('/pages/appliance/settings/ota/firmwareUpdate', {
      brand: options.brand,
      type: options.type,
      vib: options.vib,
      haId: options.haId,
    })
  }
  hideAllModal() {
    this.upgradingModalVisible.value = false
    this.successModalVisible.value = false
    this.retryModalVisible.value = false
  }
  checkUpgrade = actionDebounce({
    delay: 3000,
    call: async () => {
      this.upgradeDetected.value = false
      const res = await getEvents(this.haId, { ignoreError: true })
      const { events } = res.data
      this.handleMessages(events)
    },
  })
  checkRemoteUpgradeSupported = actionDebounce({
    delay: 3000,
    call: async () => {
      const res = await getAppSupportCommands(this.haId, { ignoreError: true })
      if (res.code !== 0) return
      const supported = res.data.commands.some((command) => command.key === ALLOW_SOFTWARE_UPDATE)
      this.remoteUpgradeSupported.value = supported
    },
  })
  allowUpgrade = actionDebounce({
    delay: 3000,
    call: async () => {
      const res = await setCommand(this.haId, ALLOW_SOFTWARE_UPDATE, true, { ignoreError: true })

      if (res.code !== 0) {
        this.retryModalVisible.value = true
      }
    },
  })
  acknowledgeSuccessful = actionDebounce({
    delay: 3000,
    call: async () => {
      await setCommand(this.haId, CONFIRM_ACKNOWLEDGE, SOFTWARE_UPDATE_SUCCESSFUL, { ignoreError: true })
      this.hideAllModal()
    },
  })

  private messageListener = (msg: WS.Message) => {
    if (msg.haId !== this.haId || !Array.isArray(msg.items)) return
    this.handleMessages(msg.items)
  }
  private addMessageListener(): void {
    useWebsocketListener(WebsocketManager.instance.inhouseWebsocket, this.messageListener)
  }
  private removeMessageListener(): void {
    WebsocketManager.instance.inhouseWebsocket.removeMessageListener(this.messageListener)
  }
  private msgMappings: MessageMappings = [
    { key: SOFTWARE_UPDATE_AVAILABLE, value: PRESENT, handler: () => (this.upgradeDetected.value = true) },
    { key: SOFTWARE_UPDATE_AVAILABLE, value: OFF, handler: this.onUpdateAvailableOff },
    { key: SOFTWARE_UPDATE_SUCCESSFUL, value: PRESENT, handler: this.onUpdateSuccessful },
    { key: SOFTWARE_UPDATE_SUCCESSFUL, value: CONFIRMED, handler: this.onAcknowledgeComplete },
  ]
  private handleMessages(messages: WS.MessageItem[]): void {
    messages.forEach((msg) => {
      const matchedMapping = this.msgMappings.find((mapping) => msg.key === mapping.key && msg.value === mapping.value)
      if (!matchedMapping) return

      matchedMapping.handler.call(this, msg)
    })
  }
  private onUpdateAvailableOff() {
    this.hideAllModal()
    this.upgradingModalVisible.value = true
  }
  private async onUpdateSuccessful() {
    this.hideAllModal()

    /**
     * 手动确认固件升级完成
     */
    if (this.successAcknowledge === 'manual') {
      // 弹出提示框，点击【知道了】按钮下发acknowledge
      this.successModalVisible.value = true
      return
    }

    /**
     * 自动确认固件升级完成
     */
    if (this.successAcknowledge === 'auto') {
      // 下发acknowledge 不再提示用户
      this.acknowledgeSuccessful().finally(() => {
        // 显示升级成功Toast
        uni.showToast({
          title: i18n.global.t('Appliance.Settings.FirmwareUpgrade.UpgradeSucess.Toast.Title'),
          icon: 'success',
        })
      })
    }
  }
  private onAcknowledgeComplete() {
    this.hideAllModal()
    // 刷新状态
    this.checkUpgrade()
  }
}
